package com.qd.pay.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.qd.pay.domain.OrderRefundReportDTO;
import com.qd.pay.model.OrderRefundReport;
import com.qd.pay.repository.OrderRefundReportRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author sjk
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderRefundReportService {

    private final OrderRefundReportRepository orderRefundReportRepository;
    @Resource
    private RedisTemplateUtil<OrderRefundReport> redisTemplateUtil;

    private static final String PREFIX_ID = "m_order_refund_report_rid_{0}";

    @Transactional(rollbackFor = Exception.class)
    public OrderRefundReport save(OrderRefundReport model) throws ApiException {
        try {
            if (!orderRefundReportRepository.save(model)) {
                throw new ApiException(ApiResult.error());
            }
            return model;
        } finally {
            clearCache(model);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(OrderRefundReport model) throws ApiException {
        final OrderRefundReport historyModel = Optional.ofNullable(getById(model.getRid())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        try {
            if (!orderRefundReportRepository.updateById(model)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean removeById(String rid) throws ApiException {
        final OrderRefundReport historyModel = Optional.ofNullable(getById(rid)).orElseThrow(() -> new ApiException("ID不存在,不能删除"));
        try {
            if (!orderRefundReportRepository.removeById(rid)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    public boolean isExistsByOrderIdAndRefundNo(String orderId, Integer refundNo) {
        return orderRefundReportRepository.getBaseMapper().exists(new QueryWrapper<OrderRefundReport>().eq("order_id", orderId).eq("refund_no", refundNo));
    }

    public OrderRefundReport getById(String rid) {
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, rid);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY * 3), () -> orderRefundReportRepository.getById(rid), OrderRefundReport.class);
    }

    public IPage<OrderRefundReportDTO> page(Page<OrderRefundReportDTO> page, OrderRefundReport model) {
        QueryWrapper<OrderRefundReport> queryWrapper = new QueryWrapper<>(model);
        IPage<OrderRefundReport> iPage = orderRefundReportRepository.page(page.convert(this::dtoToModel), queryWrapper);
        return iPage.convert(this::modelToDto);
    }

    public Integer refundTotal(String orderId, String refundStatus) {
        return orderRefundReportRepository.refundTotal(orderId, refundStatus);
    }

    private void clearCache(OrderRefundReport model) {
        if (null == model) {
            return;
        }
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getRid());
        redisTemplateUtil.deleteByKey(key);
    }

    public OrderRefundReportDTO modelToDto(OrderRefundReport model) {
        if (null == model) {
            return null;
        }
        OrderRefundReportDTO dto = new OrderRefundReportDTO();
        dto.setRid(model.getRid());
        dto.setTransactionId(model.getTransactionId());
        dto.setOutRefundNo(model.getOutRefundNo());
        dto.setTimeEnd(model.getTimeEnd());
        dto.setRefundRecvAccout(model.getRefundRecvAccout());
        dto.setRefundFee(model.getRefundFee());
        dto.setRefundStatus(model.getRefundStatus());
        dto.setRefundRequestSource(model.getRefundRequestSource());
        dto.setAddTime(model.getAddTime());
        dto.setRefundNo(model.getRefundNo());
        dto.setOrderId(model.getOrderId());
        model.freeData();
        return dto;
    }

    public OrderRefundReport dtoToModel(OrderRefundReportDTO dto) {
        if (null == dto) {
            return null;
        }
        OrderRefundReport model = new OrderRefundReport();
        model.setRid(dto.getRid());
        model.setTransactionId(dto.getTransactionId());
        model.setOutRefundNo(dto.getOutRefundNo());
        model.setTimeEnd(dto.getTimeEnd());
        model.setRefundRecvAccout(dto.getRefundRecvAccout());
        model.setRefundFee(dto.getRefundFee());
        model.setRefundStatus(dto.getRefundStatus());
        model.setRefundRequestSource(dto.getRefundRequestSource());
        model.setAddTime(dto.getAddTime());
        model.setRefundNo(dto.getRefundNo());
        model.setOrderId(dto.getOrderId());
        dto.freeData();
        return model;
    }

    public OrderRefundReport getOne(String transactionId, String outRefundNo) {
        QueryWrapper<OrderRefundReport> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transaction_id", transactionId);
        queryWrapper.eq("out_refund_no", outRefundNo);
        queryWrapper.last("limit 1");
        return orderRefundReportRepository.getOne(queryWrapper, false);
    }
}